package com.moss.cloud.base.biz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.moss.cloud.base.api.model.from.BaseFrom;
import com.moss.cloud.base.api.model.from.GatewayRoutesFrom;
import com.moss.cloud.base.api.model.param.GatewayRouteQueryParam;
import com.moss.cloud.base.biz.mapper.GatewayRoutesMapper;
import com.moss.cloud.base.biz.model.GatewayRouteVo;
import com.moss.cloud.base.biz.model.GatewayRoutes;
import com.moss.cloud.base.biz.service.IGatewayRoutesService;
import com.moss.cloud.common.core.enums.state.Deleted;
import com.moss.cloud.common.core.exception.SystemErrorType;
import com.moss.cloud.common.core.utils.BooleanHandel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * 网关路由服务层实现
 *
 * @author 瑾年
 * @date 2023年3月7日
 */
@Slf4j
@Service
public class GatewayRoutesServiceImpl extends ServiceImpl<GatewayRoutesMapper, GatewayRoutes> implements IGatewayRoutesService {
    private static final String GATEWAY_ROUTES = "gateway_routes::";

    private final StringRedisTemplate stringRedisTemplate;

    public GatewayRoutesServiceImpl(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    /**
     * 新增网关路由
     *
     * @param gatewayRoutesFrom 网关路由对象
     * @return gatewayId
     * @Author: 瑾年
     * @Date: 2020-4-23
     */
    @Override
    public Long add(GatewayRoutesFrom gatewayRoutesFrom) {
        GatewayRoutes gatewayRoute = new GatewayRoutes();
        BeanUtils.copyProperties(gatewayRoutesFrom, gatewayRoute);
        this.checkFromData(gatewayRoutesFrom, Boolean.FALSE);
        boolean flag = this.save(gatewayRoute);
        stringRedisTemplate.opsForValue().set(GATEWAY_ROUTES + gatewayRoute.getId(), toJson(new GatewayRouteVo(gatewayRoute)));
        return flag ? gatewayRoute.getId() : 0L;
    }

    /**
     * 删除网关路由
     *
     * @param baseFrom 住建
     * @Author: 瑾年
     * @Date: 2020-4-23
     */
    @Override
    public Long delete(BaseFrom baseFrom) {
        this.unificationCheck(baseFrom.getId());
        boolean flag = this.removeById(baseFrom.getId());
        stringRedisTemplate.delete(GATEWAY_ROUTES + baseFrom.getId());
        return flag ? baseFrom.getId() : 0L;
    }

    /**
     * 修改网关路由
     *
     * @param gatewayRoutesFrom 网关路由对象
     * @Author: 瑾年
     * @Date: 2020-4-23
     */
    @Override
    public Long update(GatewayRoutesFrom gatewayRoutesFrom) {
        GatewayRoutes gatewayRoute = new GatewayRoutes();
        BeanUtils.copyProperties(gatewayRoutesFrom, gatewayRoute);
        this.unificationCheck(gatewayRoutesFrom.getId());
        this.checkFromData(gatewayRoutesFrom, Boolean.TRUE);
        boolean flag = this.updateById(gatewayRoute);
        stringRedisTemplate.delete(GATEWAY_ROUTES + gatewayRoute.getId());
        stringRedisTemplate.opsForValue().set(GATEWAY_ROUTES + gatewayRoute.getId(), toJson(new GatewayRouteVo(get(gatewayRoute.getId()))));
        return flag ? gatewayRoute.getId() : 0L;
    }

    /**
     * 获取网关路由
     *
     * @param id 住建
     * @return GatewayRoute
     * @Author: 瑾年
     * @Date: 2020-4-23
     */
    @Override
    public GatewayRoutes get(long id) {
        return this.getById(id);
    }

    /**
     * 根据uri获取网关路由
     *
     * @param gatewayRouteQueryParam 查询参数
     * @return List<GatewayRoute>
     * @Author: 瑾年
     * @Date: 2020-4-23
     */
    @Override
    public List<GatewayRoutes> query(GatewayRouteQueryParam gatewayRouteQueryParam) {
        return this.list(new QueryWrapper<GatewayRoutes>().lambda()
                .ne(GatewayRoutes::getDeleted, Deleted.DELETE.code())
                .eq(StringUtils.isNotBlank(gatewayRouteQueryParam.getRouteId()),
                        GatewayRoutes::getRouteId, gatewayRouteQueryParam.getRouteId())
                .eq(StringUtils.isNotBlank(gatewayRouteQueryParam.getStatus()),
                        GatewayRoutes::getStatus, gatewayRouteQueryParam.getStatus()));
    }

    /**
     * 分页查询网关配置数据
     *
     * @param gatewayRouteQueryParam
     * @return
     */
    @Override
    public IPage<GatewayRoutes> routesPages(GatewayRouteQueryParam gatewayRouteQueryParam) {
        IPage<GatewayRoutes> gatewayRoutesIPage = new Page<>(gatewayRouteQueryParam.getCurrent(), gatewayRouteQueryParam.getSize());
        QueryWrapper<GatewayRoutes> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().ne(GatewayRoutes::getDeleted, Deleted.DELETE.code())
                .eq(StringUtils.isNotBlank(gatewayRouteQueryParam.getRouteId()),
                        GatewayRoutes::getRouteId, gatewayRouteQueryParam.getRouteId())
                .eq(StringUtils.isNotBlank(gatewayRouteQueryParam.getStatus()),
                        GatewayRoutes::getStatus, gatewayRouteQueryParam.getStatus());
        return this.page(gatewayRoutesIPage, queryWrapper);
    }

    /**
     * 搜索网关路由
     *
     * @return boolean
     * @Author: 瑾年
     * @Date: 2020-4-23
     */
    @Override
    public boolean overload() {
        List<GatewayRoutes> gatewayRoutes = this.list(new QueryWrapper<>());
        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        gatewayRoutes.forEach(gatewayRoute ->
                opsForValue.set(GATEWAY_ROUTES + gatewayRoute.getId(), toJson(new GatewayRouteVo(gatewayRoute)))
        );
        return true;
    }

    /**
     * GatewayRoute转换为json
     *
     * @param gatewayRouteVo redis需要的vo
     * @return json string
     * @Author: 瑾年
     * @Date: 2020-4-23
     */
    private String toJson(GatewayRouteVo gatewayRouteVo) {
        String routeDefinitionJson = Strings.EMPTY;
        try {
            routeDefinitionJson = new ObjectMapper().writeValueAsString(gatewayRouteVo);
        } catch (JsonProcessingException e) {
            log.error("网关对象序列化为json String", e);
        }
        return routeDefinitionJson;
    }

    /**
     * 编辑修改删除检验
     *
     * @param id
     */
    private void unificationCheck(Long id) {
        BooleanHandel.trueThrow(Objects.isNull(id)).throwMessage(SystemErrorType.PRIMARY_KEY_EMPTY);
        GatewayRoutes gatewayRoutes = this.getById(id);
        BooleanHandel.trueThrow(Objects.isNull(gatewayRoutes)).throwMessage(SystemErrorType.DATE_EMPTY);
    }

    /**
     * 新增编辑重复数据校验
     *
     * @param gatewayRoutesFrom
     * @param isUpdate
     */
    private void checkFromData(GatewayRoutesFrom gatewayRoutesFrom, Boolean isUpdate) {
        List<GatewayRoutes> gatewayRoutes = this.list(new QueryWrapper<GatewayRoutes>().lambda()
                .eq(GatewayRoutes::getRouteId, gatewayRoutesFrom.getRouteId()));
        BooleanHandel.isTrue(isUpdate).trueHandle(() -> {
            gatewayRoutes.removeIf(item -> item.getId().equals(gatewayRoutesFrom.getId()));
            BooleanHandel.trueThrow(CollectionUtils.isNotEmpty(gatewayRoutes)).throwMessage(SystemErrorType.ROUTE_ID_REPEAT);
        });
        BooleanHandel.isTrue(!isUpdate).trueHandle(() ->
                BooleanHandel.trueThrow(CollectionUtils.isNotEmpty(gatewayRoutes))
                        .throwMessage(SystemErrorType.ROUTE_ID_REPEAT));
    }
}
